package com.weishuang.monitor.employee.jobhandler.impl;

import cn.hutool.json.JSONUtil;
import com.weishuang.monitor.employee.commons.LocalDateTimeUtils;
import com.weishuang.monitor.employee.commons.SendUtils;
import com.weishuang.monitor.employee.entity.ServerProcessInfo;
import com.weishuang.monitor.employee.entity.ServerProcessInfoRequest;
import com.weishuang.monitor.employee.jobhandler.ServerHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.PlatformEnum;
import oshi.SystemInfo;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

public class ServerProcessesHandler implements ServerHandler {

    public final static Logger logger = LoggerFactory.getLogger(ServerProcessesHandler.class);

    private static final String upServerProcessUrl = "/api/serversBaseInfo/upServerProcessInfos";

    @Override
    public void run() {
        SystemInfo si = new SystemInfo();
        OperatingSystem operatingSystem = si.getOperatingSystem();
        List<OSProcess> processes = operatingSystem.getProcesses(OperatingSystem.ProcessFiltering.ALL_PROCESSES, OperatingSystem.ProcessSorting.CPU_DESC, 0);
        long total = si.getHardware().getMemory().getTotal();
        int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount();
        PlatformEnum currentPlatform = SystemInfo.getCurrentPlatform();
        List<ServerProcessInfo> serverProcessInfos = new ArrayList<>();
        for (OSProcess osProcess : processes) {
            //过滤windows的 Idel 进程
            if (osProcess.getProcessID() > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) {
                ServerProcessInfo serverProcessInfo = new ServerProcessInfo();
                serverProcessInfo.setName(osProcess.getName());
                serverProcessInfo.setPath(osProcess.getPath());
                //执行命令
                serverProcessInfo.setCommandLine(osProcess.getCommandLine());
                //进程工作目录
                serverProcessInfo.setCurrentWorkingDirectory(osProcess.getCurrentWorkingDirectory());
                //获取进程所有者的用户名。
                serverProcessInfo.setUser(osProcess.getUser());
                //获取进程所有者的用户id。
                serverProcessInfo.setUserId(osProcess.getUserID());
                //获取进程正在执行的组。
//            serverProcessInfo.setGroup(osProcess.getGroup());
//            serverProcessInfo.setGroupId(osProcess.getGroupID());
                //经常ID
                serverProcessInfo.setProcessId(osProcess.getProcessID());
                //父级进程ID
//            serverProcessInfo.setParentProcessId(osProcess.getParentProcessID());
                //进程使用的线程数
                serverProcessInfo.setThreadCount(osProcess.getThreadCount());
                //返回进程优先级
//            serverProcessInfo.setPriority(osProcess.getPriority());
                //进程虚拟内存大小
//            serverProcessInfo.setVirtualSize(osProcess.getVirtualSize());
                //分配内存大小，不包括交换内存（实际占用内存）
                serverProcessInfo.setResidentSetSize(osProcess.getResidentSetSize());
                //进程以及执行的毫秒数
                serverProcessInfo.setKernelTime(osProcess.getKernelTime());
                //进程使用的用户时间
                serverProcessInfo.setUserTime(osProcess.getUserTime());
                //启动运行的时间
                serverProcessInfo.setUpTime(osProcess.getUpTime());
                //经常启动时间
                serverProcessInfo.setStartTime(osProcess.getStartTime());
                //进程读取的字节数
                serverProcessInfo.setBytesRead(osProcess.getBytesRead());
                //进程写入的字节数
                serverProcessInfo.setBytesWritten(osProcess.getBytesWritten());
                //打开的文件或网络连接数量
                serverProcessInfo.setOpenFiles(osProcess.getOpenFiles());
                //累计cpu占用率
                if (osProcess.getProcessID() > 0 || !currentPlatform.equals(PlatformEnum.WINDOWS)) {
                    double processCpuLoadBetweenTicks;
                    //非windows
                    if (currentPlatform.equals(PlatformEnum.WINDOWS)) {
                        processCpuLoadBetweenTicks = 100d * osProcess.getProcessCpuLoadBetweenTicks(osProcess) / cpuCount;
                    }else{
                        processCpuLoadBetweenTicks = 100d * osProcess.getProcessCpuLoadBetweenTicks(osProcess);
                    }
                    serverProcessInfo.setProcessCpuLoadCumulative(new BigDecimal(String.valueOf(processCpuLoadBetweenTicks)).setScale(2,BigDecimal.ROUND_DOWN));
                }
                serverProcessInfo.setRamTotal(total);
                serverProcessInfo.setUpdatedTime(LocalDateTimeUtils.getUtcToShanghaiDate(LocalDateTime.now(ZoneOffset.UTC)));
                serverProcessInfos.add(serverProcessInfo);
            }
        }
        String s = JSONUtil.toJsonStr(serverProcessInfos);
        ServerProcessInfoRequest serverProcessInfoRequest = new ServerProcessInfoRequest();
        serverProcessInfoRequest.setProcessInfos(s);
        try {
            String s1 = SendUtils.sendRequest(upServerProcessUrl, serverProcessInfoRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
